
package chipyard_learning.parameters

import chisel3._
import org.chipsalliance.cde.config._

// case object WIDTH extends Field[Int]
// case object PA extends Field[Int]
// case object DWIDTH extends Field[Int]
// case object A_TYPE extends Field[String]


class MyConfigUp extends Config((site, here, up) =>
  {
    case WIDTH => 8
    case DWIDTH => site(A_TYPE) match {
      case "big_a" => 6
      case "small_a" => 1 
    }
  }) 

class ModuleAUp (port_width: Int)(implicit p:Parameters) extends Module{
  val width: Int = p(DWIDTH)
  val io = IO(new Bundle{
    val port_d = Input(UInt(port_width.W))
    val port_e = Output(UInt(port_width.W))
  })
  io.port_e := io.port_d + width.U
  // io.port_e := io.port_d + p(PA).U
}

class HelloWorldUp (implicit p:Parameters) extends Module {
  val width: Int = p(WIDTH)
  val io = IO(new Bundle{
    val port_a = Input(UInt(width.W))
    val port_b = Input(UInt(width.W))
    val port_c = Output(UInt(width.W))
  })
  
  val m_big_a = Module(new ModuleAUp(width)(p.alter(
    (site, here, up) => {
    case DWIDTH => 3 * up(WIDTH)
    case A_TYPE => "big_a"
    case PA => 5
  })))

  val m_small_a = Module(new ModuleAUp(width)(p.alter(
    (site, here, up) => {
    case DWIDTH => 2 * up(WIDTH)
    case A_TYPE => "small_a"
    case PA => 5
  })))

  m_big_a.io.port_d := io.port_b
  m_small_a.io.port_d := io.port_a
  io.port_c := m_big_a.io.port_e + m_small_a.io.port_e
}

object HelloWorldUp extends App{
  implicit val parames: Config = (new MyConfigUp).toInstance
  (new chisel3.stage.ChiselStage).emitVerilog(new HelloWorldUp()(parames), Array("--target-dir", "verilog/output"))
}


